"""
聊天应用核心模块

集成所有组件，提供应用程序主要功能
"""

import os
import time
import logging
import subprocess
import platform
from typing import Dict, Any, Optional, Callable

from src.core.config_manager import ConfigManager
from src.utils.audio_utils import AudioRecorder
from src.services.speech_services import SpeechServiceFactory, SpeechToText, TextToSpeech
from src.services.ai_models import ModelFactory, AIModel

# 设置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler()
    ]
)

class ChatApp:
    """聊天应用程序核心类"""
    
    def __init__(self, config_manager: Optional[ConfigManager] = None):
        """
        初始化聊天应用
        
        Args:
            config_manager: 配置管理器
        """
        # 初始化配置
        self.config_manager = config_manager or ConfigManager()
        self.config_manager.load_config()
        
        # 设置日志级别
        self.debug = self.config_manager.is_debug()
        self._setup_logging()
            
        self.logger.debug("应用初始化开始")
        
        # 初始化组件
        self._init_components()
        
        self.logger.debug("应用初始化完成")
    
    def _setup_logging(self) -> None:
        """设置日志级别"""
        log_level = self.config_manager.get_app_config().get("log_level", "info").upper()
        logging.getLogger().setLevel(getattr(logging, log_level, logging.INFO))
        
        self.logger = logging.getLogger("ChatApp")
        if self.debug:
            self.logger.setLevel(logging.DEBUG)
    
    def _init_components(self) -> None:
        """初始化应用组件"""
        try:
            # 创建音频录制器
            self._init_audio_recorder()
            
            # 创建语音转文本服务
            self._init_speech_to_text()
            
            # 创建文本转语音服务
            self._init_text_to_speech()
            
            # 创建AI模型
            self._init_ai_model()
            
            # 创建临时目录
            self._init_temp_directory()
                
        except Exception as e:
            self.logger.error(f"初始化组件失败: {e}")
            raise
    
    def _init_audio_recorder(self) -> None:
        """初始化音频录制器"""
        audio_config = self.config_manager.get_audio_config()
        self.audio_recorder = AudioRecorder(audio_config, self.debug)
        self.logger.debug(f"音频录制器初始化完成，配置: {audio_config}")
    
    def _init_speech_to_text(self) -> None:
        """初始化语音转文本服务"""
        stt_config = self.config_manager.get_stt_config()
        self.stt_service = SpeechServiceFactory.create_stt(stt_config, self.debug)
        self.logger.debug(f"语音转文本服务初始化完成，配置: {stt_config}")
    
    def _init_text_to_speech(self) -> None:
        """初始化文本转语音服务"""
        tts_config = self.config_manager.get_tts_config()
        self.tts_service = SpeechServiceFactory.create_tts(tts_config, self.debug)
        self.logger.debug(f"文本转语音服务初始化完成，配置: {tts_config}")
    
    def _init_ai_model(self) -> None:
        """初始化AI模型"""
        ai_config = self.config_manager.get_ai_config()
        self.ai_model = ModelFactory.create_model(ai_config, self.debug)
        self.logger.debug(f"AI模型初始化完成，配置: {ai_config}")
    
    def _init_temp_directory(self) -> None:
        """初始化临时目录"""
        audio_config = self.config_manager.get_audio_config()
        temp_dir = audio_config.get("temp_dir", "temp")
        if not os.path.exists(temp_dir):
            os.makedirs(temp_dir)
            self.logger.debug(f"创建临时目录: {temp_dir}")
    
    def play_audio(self, audio_file: str) -> bool:
        """
        使用系统命令播放音频文件
        
        Args:
            audio_file: 音频文件路径
            
        Returns:
            是否成功播放
        """
        if not os.path.exists(audio_file):
            self.logger.error(f"音频文件不存在: {audio_file}")
            return False
            
        self.logger.debug(f"开始播放音频: {audio_file}")
        
        try:
            system = platform.system()
            
            if system == "Darwin":  # macOS
                subprocess.run(["afplay", audio_file], check=True)
                return True
            elif system == "Linux":
                subprocess.run(["aplay", audio_file], check=True)
                return True
            elif system == "Windows":
                import winsound
                winsound.PlaySound(audio_file, winsound.SND_FILENAME)
                return True
            else:
                self.logger.error(f"不支持的操作系统: {system}")
                return False
                
        except Exception as e:
            self.logger.error(f"播放音频时发生错误: {e}")
            return False
    
    def process_audio_file(self, file_path: str) -> Optional[str]:
        """
        处理本地音频文件
        
        Args:
            file_path: 音频文件路径
            
        Returns:
            有效的音频文件路径或None
        """
        return self.audio_recorder.validate_audio_file(file_path)
    
    def run_conversation(self, audio_file: Optional[str] = None, 
                         callback: Optional[Callable[[Dict[str, Any]], None]] = None) -> None:
        """
        运行对话循环
        
        Args:
            audio_file: 音频文件路径，如果为None则进行实时录音
            callback: 回调函数，每完成一轮对话就调用一次
        """
        self.logger.info("AI对话系统已启动，按Ctrl+C退出")
        
        try:
            while True:
                conversation_data = self._run_single_conversation(audio_file)
                
                # 调用回调函数
                if callback and conversation_data:
                    try:
                        callback(conversation_data)
                    except Exception as e:
                        self.logger.error(f"回调函数执行失败: {e}")
                
                if audio_file:
                    break  # 如果是处理本地文件，只处理一次就退出
                
        except KeyboardInterrupt:
            self.logger.info("\n程序已退出")
        except Exception as e:
            self.logger.error(f"发生错误: {e}")
            if self.debug:
                import traceback
                self.logger.error(traceback.format_exc())
    
    def _run_single_conversation(self, audio_file: Optional[str] = None) -> Optional[Dict[str, Any]]:
        """
        运行单次对话
        
        Args:
            audio_file: 音频文件路径，如果为None则进行实时录音
            
        Returns:
            对话数据字典，如果出错则返回None
        """
        conversation_data = {}
        start_time = time.time()
        
        try:
            # 获取音频
            audio_path = self._get_audio_input(audio_file)
            if not audio_path:
                return None
            
            conversation_data["audio_path"] = audio_path
            
            # 语音转文本
            text = self.stt_service.transcribe_audio(audio_path)
            # conversation_data["user_text"] = text
            text = "你好"
            self.logger.info(f"你说: {text}")
            
            # 与AI对话
            response = self.ai_model.generate_response(text)
            conversation_data["ai_response"] = response
            self.logger.info(f"AI回复: {response}")
            
            # 文本转语音并播放
            audio_output = self.tts_service.synthesize_speech(response)
            if audio_output:
                conversation_data["audio_output"] = audio_output
                # 播放生成的音频
                self.play_audio(audio_output)
            
            # 计算对话完成时间
            elapsed = time.time() - start_time
            conversation_data["elapsed_time"] = elapsed
            self.logger.debug(f"对话完成，耗时: {elapsed:.2f}秒")
            
            return conversation_data
            
        except Exception as e:
            self.logger.error(f"对话过程中发生错误: {e}")
            if self.debug:
                import traceback
                self.logger.error(traceback.format_exc())
            return None
    
    def _get_audio_input(self, audio_file: Optional[str]) -> Optional[str]:
        """
        获取音频输入
        
        Args:
            audio_file: 音频文件路径，如果为None则进行实时录音
            
        Returns:
            音频文件路径，如果出错则返回None
        """
        if audio_file:
            self.logger.info(f"正在处理文件: {audio_file}")
            audio_path = self.process_audio_file(audio_file)
            if not audio_path:
                self.logger.error(f"无效的音频文件: {audio_file}")
                return None
        else:
            audio_path = self.audio_recorder.record_audio()
            if not audio_path:
                self.logger.error("录音失败")
                return None
                
        return audio_path 